import datetime
from time import sleep

from hex_tool import extract_and_convert_to_bcd, \
    bytes_to_hex_string_with_spaces, str_to_bcd_bytes
from sqlite_tool import SQLiteTool
from PrecisionLevel import PrecisionLevel


class ProtocolParser:
    def __init__(self):
        self.START_BYTE = 0x75
        self.CONTROL_CODE = 0x80
        self.SEQ = 0x00
        self.DATA_LEN = 0x11
        self.FUN_CODE = bytes([0x09, 0x01])
        self.DATA = bytes([])
        self.CHECK = 0x13
        self.END_BYTE = 0xE7

    @staticmethod
    def filter_data(bytes_data, start, end, filter_data=None):
        if start < 0 or end > len(bytes_data) or start >= end:
            raise ValueError("开始或结束索引不合理")

        sub_bytes = bytes_data[start:end]
        if filter_data is None:
            return sub_bytes
        else:
            return bytes([b for b in sub_bytes if b != filter_data])

    def parse(self, data):
        start_index = data.find(self.START_BYTE)
        end_index = data.find(self.END_BYTE)
        if start_index == -1 or end_index == -1:
            raise ValueError("无效的数据，没有找到开始或结束字节")

        basic_info = self.parse_basic_info(data)
        ratio_param = self.parse_ratio_param(data)

        db_tool = SQLiteTool()
        basic_id = db_tool.dynamic_insert_or_update('T_BASIC_INFO', basic_info)
        ratio_param['info_id'] = basic_id

        info_id = db_tool.dynamic_insert_or_update('T_RATIO_PARAM', ratio_param)
        print('basic_id', basic_id, info_id)

        return info_id, PrecisionLevel.from_byte(data[77])

    @staticmethod
    def parse_basic_info(data):
        date_today = datetime.date.today().strftime("%Y%m%d")
        category = '电流互感器' if data[13] == 0x01 else '电压互感器'
        return {
            'task_id': date_today,
            'category': category,
            'data_status': 0,
            't_id': extract_and_convert_to_bcd(data, 36, 47).replace('f', ''),
            'bar_code': extract_and_convert_to_bcd(data, 36, 47).replace('f', ''),
            'asset_no': extract_and_convert_to_bcd(data, 36, 47).replace('f', ''),
            'made_no': extract_and_convert_to_bcd(data, 36, 47).replace('f', ''),
            'rated_volt': int(extract_and_convert_to_bcd(data, start_index=79, end_index=81, byteorder='little')) / 10,
            'rated_freq': int(extract_and_convert_to_bcd(data, start_index=81, end_index=83, byteorder='little')) / 10
        }

    @staticmethod
    def parse_ratio_param(data):
        class_ctpt = 'CT' if data[13] == 0x01 else 'PT'
        return {
            'class_ctpt': class_ctpt,
            'fst_val': int(extract_and_convert_to_bcd(data, start_index=63, end_index=66,
                                                      byteorder='little')) / 10000 if class_ctpt == 'CT' else
            int(extract_and_convert_to_bcd(data, start_index=67, end_index=69, byteorder='little')) / 10,
            'snd_val': int(extract_and_convert_to_bcd(data, start_index=66 if class_ctpt == 'CT' else 69,
                                                      end_index=67 if class_ctpt == 'CT' else 71, byteorder='little')),
            'rated_load': int(extract_and_convert_to_bcd(data, start_index=71, end_index=74, byteorder='little')) / 100,
            'floor_load': int(extract_and_convert_to_bcd(data, start_index=74, end_index=77, byteorder='little')) / 100,
            'accuracy': PrecisionLevel.from_byte(data[77]),
            'power_factor': int(
                extract_and_convert_to_bcd(data, start_index=78, end_index=79, byteorder='little')) / 10,
            'rated_freq': int(extract_and_convert_to_bcd(data, start_index=81, end_index=83, byteorder='little')) / 10
        }

    def construct(self, timer, content, client_sock, level):
        if not content:
            print('无数据')
            return
        sleep(1)
        for i in content:
            if i[0] == '1':
                if i[1] == '1':
                    self.FUN_CODE = bytes([0x09, 0x01])
                if i[1] == '0':
                    self.FUN_CODE = bytes([0x09, 0x06])
            elif i[0] == '5':
                if i[1] == '1':
                    self.FUN_CODE = bytes([0x09, 0x02])
                if i[1] == '0':
                    self.FUN_CODE = bytes([0x09, 0x07])
            elif i[0] == '20' or i[0] == '80':
                if i[1] == '1':
                    self.FUN_CODE = bytes([0x09, 0x03])
                if i[1] == '0':
                    self.FUN_CODE = bytes([0x09, 0x08])
            elif i[0] == '100':
                if i[1] == '1':
                    self.FUN_CODE = bytes([0x09, 0x04])
                if i[1] == '0':
                    self.FUN_CODE = bytes([0x09, 0x09])
            elif i[0] == '120' or i[0] == '115':
                if i[1] == '1':
                    self.FUN_CODE = bytes([0x09, 0x05])
                if i[1] == '0':
                    self.FUN_CODE = bytes([0x09, 0x0A])
            else:
                continue

            self.DATA = bytes([0x11, 0x22, 0x33, 0x44, 0x55, 0x66])

            if level == '0.01' or level == '0.02' or level == '0.05':
                self.DATA += bytes([0x00])
                self.DATA += str_to_bcd_bytes(
                    i[2]) + str_to_bcd_bytes(i[3], 2)
            elif level == '0.1' or level == '0.2' or level == '0.2S' or level == '0.5' or level == '0.5S':
                self.DATA += bytes([0x01])
                self.DATA += str_to_bcd_bytes(
                    i[2], 2) + str_to_bcd_bytes(i[3], 3)
            elif level == '1.0' or level == '1':
                self.DATA += bytes([0x02])
                self.DATA += str_to_bcd_bytes(
                    i[2], 3) + str_to_bcd_bytes(i[3], 2)

            self.SEQ += 1
            if self.SEQ > 0xff:
                self.SEQ = 0x01

            combined_bytes = bytes([
                self.START_BYTE,
                self.CONTROL_CODE,
                self.SEQ,
                self.DATA_LEN
            ])
            combined_bytes += self.FUN_CODE
            combined_bytes += self.DATA
            combined_bytes += bytes([self.CHECK, self.END_BYTE])
            print('开始发送：', i)
            client_sock.send(combined_bytes)
            from datetime import datetime
            import pytz

            beijing_time = datetime.now(pytz.timezone('Asia/Shanghai'))
            print(
                f"{combined_bytes[2]}[{beijing_time.strftime('%Y-%m-%d %H:%M:%S')}] 已发送数据: {bytes_to_hex_string_with_spaces(combined_bytes).upper()}\n")

            # print(f"{combined_bytes[2]} 已发送数据: {bytes_to_hex_string_with_spaces(combined_bytes).upper()}\n")
            sleep(1)
        # sleep(1)
        _str = '75 80 01 0B 08 01 11 22 33 44 55 66 0E 0D E7'
        data_bytes = bytes.fromhex(_str)
        client_sock.send(data_bytes)
        print(f"已发送{data_bytes[2]}数据: {_str}")
        timer.control_callback('stop')
